package com.zhs.demoutil.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhs.demoutil.dao.TableRecordDao;
import com.zhs.demoutil.dao.TmpCheckResultDao;
import com.zhs.demoutil.entity.*;
import com.zhs.demoutil.listener.TmpCheckResultListener;
import com.zhs.demoutil.service.*;
import com.zhs.demoutil.util.CmdUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TmpCheckResultServiceImpl extends ServiceImpl<TmpCheckResultDao, TmpCheckResult> implements TmpCheckResultService {

    @Resource
    private CheckPointService checkPointService;
    @Resource
    private CheckResultProService checkResultProService;
    @Resource
    private FileRecordService fileRecordService;
    @Resource
    private AdminService adminService;
    @Resource
    private TableRecordDao tableRecordDao;


    @Override
    public String addByExcel(MultipartFile file) {

        // 读之前确认表里面没数据，有数据的话需要清空数据
        String path = "/tmp/file/"+System.currentTimeMillis()+"/"+file.getOriginalFilename();
        try {
            File dest = new File(path);
            if(!dest.exists()){
                dest.mkdirs();
            }
            file.transferTo(dest);
        } catch (IOException e) {
            log.error("文件读取失败");
            throw new RuntimeException("文件读取失败",e);
        }
        return addByExcel(path);
    }

    @Override
    public String addByExcel(String path) {
        baseMapper.delete(new QueryWrapper<>());
        // 读之前确认表里面没数据，有数据的话需要清空数据

        EasyExcel.read(path, TmpCheckResult.class, new TmpCheckResultListener(this)).sheet().doRead();
        return onlyGet();
    }

    @Override
    public String onlyGet() {
        // 查询历城区所有的街道
        QueryWrapper<CheckPoint> checkPointQueryWrapper = new QueryWrapper<>();
        checkPointQueryWrapper.eq("region","历城区");
        List<CheckPoint> list = checkPointService.list(checkPointQueryWrapper);
        List<String> streetList = list.stream().map(CheckPoint::getStreet).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        long currentTimeMillis = System.currentTimeMillis();
        String prefixPath = "/data/file/export/"+currentTimeMillis+"/";
        File file1 = new File(prefixPath);
        if(!file1.exists()){
            file1.mkdirs();
        }
        if(streetList.size()==0){
            String excelPath = prefixPath+"无符合条件数据"+".xlsx";
            ExcelWriter excelWriter = null;
            try {
                excelWriter = EasyExcel.write(excelPath, TmpCheckResult.class).build();
                WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
                excelWriter.write(new ArrayList<>(), writeSheet);
            }finally {
                // 千万别忘记finish 会帮忙关闭流
                if (excelWriter != null) {
                    excelWriter.finish();
                }
            }
        }
        // 新建表，然后把没做核算的数据存储到表里
        String tableName = "no_check_result_"+ currentTimeMillis;
        baseMapper.createTable(tableName);
        TableRecord tableRecord = new TableRecord();
        tableRecord.setBatch(currentTimeMillis);
        tableRecord.setTableName(tableName);
        tableRecordDao.insert(tableRecord);
        for (String street : streetList) {
            // 查询每个街道的数据
            // 导出每个区的
            String excelPath = prefixPath+street+".xlsx";
            File excel = new File(excelPath);
            if(!excel.getParentFile().exists()){
                excel.getParentFile().mkdirs();
            }
            ExcelWriter excelWriter = null;
            try {
                // 这里 需要指定写用哪个class去写
                excelWriter = EasyExcel.write(excelPath, TmpCheckResult.class).build();
                // 这里注意 如果同一个sheet只要创建一次
                WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
                // 去调用写入,这里我调用了五次，实际使用时根据数据库分页的总的页数来
                int offset = 0;
                int size = 1000;
                while (true){
                    List<TmpCheckResult> data =  baseMapper.listNoCheck(street,offset,size);
                    excelWriter.write(data, writeSheet);
                    // 写入数据库
                    offset+=1000;
                    if(data.size()==0){
                        break;
                    }
                    baseMapper.insertTmpTableList(data,street,tableName);
                    // 释放内存
                    data.clear();
                    data = null;
                }
            } finally {
                // 千万别忘记finish 会帮忙关闭流
                if (excelWriter != null) {
                    excelWriter.finish();
                }
            }
            // 查询街道的人
            List<Long> adminIdList = adminService.listByStreet(street);
            for (Long adminId : adminIdList) {
                FileRecord fileRecord = new FileRecord();
                fileRecord.setFilePath(excelPath);
                fileRecord.setAdminId(adminId);
                fileRecord.setFileName(street+".xlsx");
                fileRecord.setRegion("历城区");
                fileRecord.setStreet(street);
                fileRecordService.save(fileRecord);
            }

        }
        // prefix 进行打包，然后
        String zipPath =  "/tmp/file/export/"+currentTimeMillis+".zip";
        try {
            CmdUtils.executeCmd("zip -r -qj -o "+zipPath +" " +prefixPath);
        } catch (IOException e) {
            log.error("打包失败",e);
        }
        // 反向查询，多余的进入增量库

        int offset = 0;
        int size = 1000;
        while (true){
            List<CheckResultPro> data = baseMapper.listPro(offset,size);
            // 查询原始是否存在，不存在的
            offset+=1000;
            if(data.size()==0){
                break;
            }
            checkResultProService.saveOrUpdateBatchByCardNumber(data);
        }
        return zipPath;
    }
}
